﻿using MQTTnet;
using MQTTnet.Client.Receiving;
using MQTTnet.Protocol;
using MQTTnet.Server;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ERPWinFormWork.Material
{
    public partial class MQTTX : Form
    {
        private IMqttServer server;//mqtt服务器对象
        List<MaterialTopicltem> Topics = new List<MaterialTopicltem>();

        public MQTTX()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 启动
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void btnStart_Click(object sender, EventArgs e)
        {
            try
            {
                if (server == null)
                {
                    // 确保服务器对象已创建
                    server = new MqttFactory().CreateMqttServer();
                    InitializeServerEvents();
                }

                if (server.IsStarted)
                {
                    WriteLog(">>> 服务器已在运行中");
                    return;
                }

                var optionBuilder = new MqttServerOptionsBuilder()
                    .WithDefaultEndpointBoundIPAddress(System.Net.IPAddress.Parse(this.tbxIP.Text))
                    .WithDefaultEndpointPort(int.Parse(this.tbx端口.Text))
                    .WithDefaultCommunicationTimeout(TimeSpan.FromMilliseconds(5000))
                    .WithConnectionValidator(x =>
                    {
                        string un = this.tbx账号.Text;
                        string pwd = this.tbxpassword.Text;

                        if (x.Username != un || x.Password != pwd)
                        {
                            x.ReturnCode = MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
                        }
                        else
                        {
                            x.ReturnCode = MqttConnectReturnCode.ConnectionAccepted;
                        }
                    });

                var option = optionBuilder.Build();
                await server.StartAsync(option);
                WriteLog(">>> 服务器启动成功");
            }
            catch (Exception ex)
            {
                WriteLog($">>> 启动服务器失败: {ex.Message}");
            }


        }
        /// <summary>
        /// 停止
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void btnEnd_Click(object sender, EventArgs e)
        {
            try
            {
                if (server != null && server.IsStarted)
                {
                    await server.StopAsync();
                    WriteLog(">>> 服务器已停止");
                }
                else
                {
                    WriteLog(">>> 服务器未在运行中");
                }
            }
            catch (Exception ex)
            {
                WriteLog($">>> 停止服务器失败: {ex.Message}");
            }

        }

        /// <summary>
        /// 初始化服务器事件
        /// </summary>
        private void InitializeServerEvents()
        {
            server.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(Server_ApplicationMessageReceived);
            server.ClientConnectedHandler = new MqttServerClientConnectedHandlerDelegate(Server_ClientConnected);
            server.ClientDisconnectedHandler = new MqttServerClientDisconnectedHandlerDelegate(Server_ClientDisconnected);
            server.ClientSubscribedTopicHandler = new MqttServerClientSubscribedHandlerDelegate(Server_ClientSubscribedTopic);
            server.ClientUnsubscribedTopicHandler = new MqttServerClientUnsubscribedTopicHandlerDelegate(Server_ClientUnsubscribedTopic);

        }


        /// <summary>
        /// 绑定消息接收事件
        /// </summary>
        /// <param name="e"></param>
        private void Server_ApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs e)
        {
            string msg = e.ApplicationMessage.ConvertPayloadToString();
            WriteLog(">>> 收到消息：" + msg + "，QoS =" + e.ApplicationMessage.QualityOfServiceLevel + "，客户端=" + e.ClientId + "，主题：" + e.ApplicationMessage.Topic);
        }

        /// <summary>
        /// 绑定客户端连接事件
        /// </summary>
        /// <param name="e"></param>
        private void Server_ClientConnected(MqttServerClientConnectedEventArgs e)
        {
            Task.Run(new Action(() =>
            {
                lbx在线.BeginInvoke(new Action(() =>
                {
                    lbx在线.Items.Add(new CCWin.SkinControl.SkinListBoxItem(e.ClientId));
                }));
            }));
            WriteLog(">>> 客户端" + e.ClientId + "连接");
        }

        /// <summary>
        /// 绑定客户端断开事件
        /// </summary>
        /// <param name="e"></param>
        private void Server_ClientDisconnected(MqttServerClientDisconnectedEventArgs e)
        {
            Task.Run(new Action(() =>
            {
                lbx在线.BeginInvoke(new Action(() =>
                {
                    lbx在线.Items.Remove(new CCWin.SkinControl.SkinListBoxItem(e.ClientId));
                }));
            }));
            WriteLog(">>> 客户端" + e.ClientId + "断开");
        }

        /// <summary>
        /// 绑定客户端订阅主题事件
        /// </summary>
        /// <param name="e"></param>
        private void Server_ClientSubscribedTopic(MqttServerClientSubscribedTopicEventArgs e)
        {
            Task.Run(new Action(() =>
            {
                var topic = Topics.FirstOrDefault(t => t.Topic == e.TopicFilter.Topic);
                if (topic == null)
                {
                    topic = new MaterialTopicltem { Topic = e.TopicFilter.Topic, Count = 0 };
                    Topics.Add(topic);
                }
                if (!topic.Clients.Exists(c => c == e.ClientId))
                {
                    topic.Clients.Add(e.ClientId);
                    topic.Count++;
                }

                lbx列表.Invoke(new Action(() =>
                {
                    this.lbx列表.Items.Clear();
                }));

                foreach (var item in this.Topics)
                {

                    lbx列表.Invoke(new Action(() =>
                    {
                        this.lbx列表.Items.Add(new CCWin.SkinControl.SkinListBoxItem($"{item.Topic}:{item.Count}"));
                    }));
                }
            }));
            WriteLog(">>> 客户端" + e.ClientId + "订阅主题" + e.TopicFilter.Topic);
        }

        /// <summary>
        /// 绑定客户端退订主题事件
        /// </summary>
        /// <param name="e"></param>
        private void Server_ClientUnsubscribedTopic(MqttServerClientUnsubscribedTopicEventArgs e)
        {
            Task.Run(new Action(() =>
            {
                var topic = Topics.FirstOrDefault(t => t.Topic == e.TopicFilter);
                if (topic != null)
                {
                    topic.Count--;
                    topic.Clients.Remove(e.ClientId);
                }

                this.lbx列表.Items.Clear();
                foreach (var item in this.Topics)
                {
                    this.lbx列表.Items.Add(new CCWin.SkinControl.SkinListBoxItem($"{item.Topic}:{item.Count}"));
                }
            }));

            WriteLog(">>> 客户端" + e.ClientId + "退订主题" + e.TopicFilter);
        }

        /// <summary>
        /// 绑定服务端启动事件
        /// </summary>
        /// <param name="e"></param>
        private void Server_Started(EventArgs e)
        {
            WriteLog(">>> 服务端已启动！");
        }

        /// <summary>
        /// 绑定服务端停止事件
        /// </summary>
        /// <param name="e"></param>
        private void Server_Stopped(EventArgs e)
        {
            WriteLog(">>> 服务端已停止！");
        }

        /// <summary>
        /// 显示日志 - 修改后会保留历史消息
        /// </summary>
        /// <param name="message"></param>
        public void WriteLog(string message)
        {
            // 添加时间戳，方便查看消息时间
            string logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {message}\r\n";

            if (rtb消息.InvokeRequired)
            {
                rtb消息.Invoke(new Action(() =>
                {
                    // 将新消息追加到现有内容前，最新消息显示在上面
                    //textXX.Text = logMessage + textXX.Text;
                    // 或者追加到后面，最新消息显示在下面
                    rtb消息.Text += logMessage;
                }));
            }
            else
            {
                rtb消息.Text += logMessage;
            }
        }
        /// <summary>
        /// 发送信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSend_Click(object sender, EventArgs e)
        {
            // 1. 校验IP地址（必填）
            if (string.IsNullOrWhiteSpace(this.tbxIP.Text))
            {
                MessageBox.Show("请先输入MQTT服务器IP地址！", "参数缺失",
                                MessageBoxButtons.OK, MessageBoxIcon.Warning);
                this.tbxIP.Focus(); // 聚焦到IP输入框，方便用户直接填写
                return;
            }

            // 2. 校验端口（必填 + 有效数字）
            if (string.IsNullOrWhiteSpace(this.tbx端口.Text))
            {
                MessageBox.Show("请先输入MQTT服务器端口号！", "参数缺失",
                                MessageBoxButtons.OK, MessageBoxIcon.Warning);
                this.tbx端口.Focus();
                return;
            }


            // 3. 校验账号（必填）
            if (string.IsNullOrWhiteSpace(this.tbx账号.Text))
            {
                MessageBox.Show("请先输入MQTT服务器账号！", "参数缺失",
                                MessageBoxButtons.OK, MessageBoxIcon.Warning);
                this.tbx账号.Focus();
                return;
            }

            // 4. 校验密码（必填）
            if (string.IsNullOrWhiteSpace(this.tbxpassword.Text))
            {
                MessageBox.Show("请先输入MQTT服务器密码！", "参数缺失",
                                MessageBoxButtons.OK, MessageBoxIcon.Warning);
                this.tbxpassword.Focus();
                return;
            }

            // 提取主窗体中的必要信息
            string ip = this.tbxIP.Text;
            int port = int.Parse(this.tbx端口.Text);
            string username = this.tbx账号.Text;
            string password = this.tbxpassword.Text;

            // 提取所有主题
            List<string> topics = Topics.Select(t => t.Topic).ToList();

            // 检查是否有主题
            if (topics.Count == 0)
            {
                MessageBox.Show("当前没有可用的主题，请先让客户端订阅一些主题！", "无可用主题",
                                MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            // 创建并显示发送表单，传递必要信息
            发送到 发送 = new 发送到(ip, port, username, password, topics);
            发送.Show();
        }
    }

}
